#include "user.h"
#include "GPIO.h"
#include <avr/pgmspace.h>
#include <string.h>
typedef enum 
{
	DATA_READY_TO_SEND = 0,
	SET_UART_OUT,
	GET_UART_IN,
	START_SENDING,
	END_SENDING,
	UART_IDLE
}uart_send_e;

uart_send_e uart_status;
S8* cmd_str[MAX_LED] __attribute__((progmem)) 
= {
	"cmd0",		"cmd1",		"cmd2",		"cmd3",		"cmd4",
	"cmd5",		"cmd6",		"cmd7",		"cmd8",		"cmd9",

	"cmd10",	"cmd11",	"cmd12",	"cmd13",	"cmd14",
	"cmd15",	"cmd16",	"cmd17",	"cmd18",	"cmd19",

	"cmd20",	"cmd21",	"cmd22",	"cmd23",	"cmd24",
	"cmd25",	"cmd26",	"cmd27",	"cmd28",	"cmd29",

	"cmd30",	"cmd31"
};

S8* Cur_cmd_str = NULL;

#define BAUDRATE	(19200)
#define COMPORTNo
#define BAUDREG      ((unsigned int)(F_CPU / (16UL * BAUDRATE) - 1))

#ifdef URSEL
#define USEURSEL           (1 << URSEL)
#else
#define USEURSEL           0
#endif

void init_uart0(void)
{
#if 0
	U16 rate = baudrate;
	rate = 115200;

	//UART0 initialize
	// char size: 8 bit
	// parity: Disabled
	{ 
		UCSRB = 0x00; //disable while setting baud rate
		UCSRA = 0x00;
		UCSRC = (1<<URSEL) | 0x06;
		UBRRL = 0x2F; //set baud rate lo
		UBRRH = 0x00; //set baud rate hi
		UCSRB = 0xD8;
	}
	UCSRB=(1<<RXCIE)|(1<<TXCIE)|(1<<RXEN)|(1<<TXEN);
	UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);

	UBRRH=(U8)((F_CPU/baudrate/16-1) >>8);
	UBRRL=(U8)(F_CPU/baudrate/16-1)
#endif
	UBRRHREG(COMPORTNo) = BAUDREG/256;
	UBRRLREG(COMPORTNo) = BAUDREG%256;
	UCSRAREG(COMPORTNo) = 0;
	UCSRBREG(COMPORTNo) = (1<<TXCIEBIT(COMPORTNo))|(1<<RXCIEBIT(COMPORTNo))|(1 << RXENBIT(COMPORTNo))|(1 << TXENBIT(COMPORTNo));
	UCSRCREG(COMPORTNo) = USEURSEL|(1 << UCSZBIT(COMPORTNo, 1))|(1 << UCSZBIT(COMPORTNo, 0));
}

#define	UART_GPI_GROUP (GPIO_PB)
#define	UART_GPI_INDEX (3)

#define	UART_GPO_GROUP (GPIO_PB)
#define	UART_GPO_INDEX (4)


#define PREPARE_SEND_CMD	Set_GPIO_bit_output(UART_GPI_GROUP, UART_GPI_INDEX, 1);

#define	END_SEND_CMD		Set_GPIO_bit_output(UART_GPI_GROUP, UART_GPI_INDEX, 0);

#define	CHECK_MAINBOARD_OUT get_GPIO_bit(UART_GPO_GROUP, UART_GPO_INDEX)

#define	SET_DATA_OUT_BUFFER(out_data)	{UDR = out_data;}
void uart_start_send(void)
{
	SET_DATA_OUT_BUFFER(pgm_read_byte(Cur_cmd_str));
	Cur_cmd_str ++;
}

void uart_send_key_cmd(U8 key_num)
{
	Cur_cmd_str = cmd_str[key_num];
	uart_start_send();
}


void send_cmd_in_interrupt()
{
#if 0
	//clear interrupt
	if( *Cur_cmd_str != 0x00)	//end of cmd
	{
		SET_DATA_OUT_BUFFER(*Cur_cmd_str);
		Cur_cmd_str ++;
	}
	else
	{
		uart_status = END_SENDING;
	}
#endif
	if( pgm_read_byte(Cur_cmd_str)!= 0x00)	//end of cmd
	{
		SET_DATA_OUT_BUFFER(pgm_read_byte(Cur_cmd_str));
		Cur_cmd_str ++;
	}
	else
	{
		uart_status = END_SENDING;
	}
}

//#pragma interrupt_handler uart0_tx_isr: iv_USART_TXC
//void uart0_tx_isr(void)
ISR(USART_TXC_vect)
{
	if(uart_status == START_SENDING)
	{
		send_cmd_in_interrupt();
	}
}


U8 cfg_buf[8];
U8 cfg_buf_index = 0;
typedef enum 
{
	START_GET_CFG = 0,
	END_CFG,
	CFG_NULL
}uart_cfg_e;

void parse_cfg_info(void)
{
	if((cfg_buf[0] != 'c') || (cfg_buf[0] != 'f') || (cfg_buf[0] != 'g') )
	{
		return;
	}
	/*
	
	*/
}


/************************************************************
uart config 
*************************************************************/
uart_cfg_e cfg_status = CFG_NULL;
void Uart_get_config(void)
{
	switch((U8)cfg_status)
	{
	
		case START_GET_CFG:
			if(!CHECK_MAINBOARD_OUT)
			{
				cfg_status = END_CFG;
			}
			break;

		case END_CFG:
			parse_cfg_info();
			cfg_status = CFG_NULL;
			break;
	
		case CFG_NULL:
			if(CHECK_MAINBOARD_OUT)
			{
				cfg_status = START_GET_CFG;
			}			
			break;
	}
}




//#pragma interrupt_handler uart0_rx_isr:iv_USART_RXC
//void uart0_rx_isr(void)
ISR(USART_RXC_vect)
{ 
	//if((UCSRA & (FRAMING_ERROR | DATA_OVERRUN))==0)
	{
		if(cfg_buf_index < sizeof(cfg_buf) /sizeof(U8))
		{
			cfg_buf[cfg_buf_index] = UDR;
			cfg_buf_index ++;
		}
		
		if( cfg_buf_index == sizeof(cfg_buf) /sizeof(U8))
		{
			cfg_status = END_CFG;
		}
	}
}



void Uart_start_send_cmd(void)
{
	switch((U8)uart_status)
	{
		case SET_UART_OUT:
				//PREPARE_SEND_CMD;
				uart_status = GET_UART_IN;
			break;
			
		case GET_UART_IN:
				//if( CHECK_MAINBOARD_OUT)
				{
					uart_status = START_SENDING;
				}
			break;
			
		case START_SENDING:
				uart_start_send();
			break;
			
		case END_SENDING:
				END_SEND_CMD;
			break;
			
		case UART_IDLE:
		default:
			break;
	}
}
